home *** CD-ROM | disk | FTP | other *** search
/ X User Tools / X User Tools (O'Reilly and Associates)(1994).ISO / sun4c / archive / xboard.z / xboard / bin / cmail next >
Text File  |  1994-09-27  |  47KB  |  1,199 lines

  1. #!///////////////////////////////////////////////////////////////////////////usr/STAGE/bin/perl
  2. ## (Change the top line to reflect the location of perl on your system)
  3. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  4. ## cmail $Revision: 2.10 $: a tool to aid playing chess by email
  5. ## Copyright (C) 1993  Free Software Foundation, Inc.
  6. ##
  7. ## cmail is free software; you can redistribute it and/or modify
  8. ## it under the terms of the GNU General Public License as published by
  9. ## the Free Software Foundation; either version 2 of the License, or
  10. ## (at your option) any later version.
  11. ##
  12. ## cmail is distributed in the hope that it will be useful,
  13. ## but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. ## GNU General Public License for more details.
  16. ##
  17. ## You should have received a copy of the GNU General Public License
  18. ## along with cmail; if not, write to the Free Software
  19. ## Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. ##
  21. ## Modified:  $Date: 1994/05/31 18:35:21 $
  22. ## Revision:  $Revision: 2.10 $
  23. ## Email:     welsh@epcc.ed.ac.uk
  24. ## Snailmail: Evan Welsh
  25. ##            Edinburgh Parallel Computing Centre
  26. ##            JCMB, Kings Buildings
  27. ##            The University of Edinburgh
  28. ##            Edinburgh EH9 3JZ
  29. ##            Scotland
  30. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  31.  
  32.  
  33. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  34. ## Print verbose diagnostics for debugging
  35. sub debug {
  36.     if ($DEBUG) {
  37.     $old = select ;        ## Remember the selected output
  38.     select(logfile) ;    ## Diagnostics go to logfile
  39.     $| = 1 ;        ## Keep it flushed
  40.     for ($i = 0 ; $i <= $#_ ; $i ++) {
  41.         printf($_[$i]) ;    ## Print one or more diagnostic messages
  42.     }
  43.     select($old) ;        ## Re-select the old output
  44.     }
  45. }
  46. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  47.  
  48.  
  49. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  50. ## Create a directory for storing games in if it doesn't already exist
  51. sub need_chess_dir {
  52.     ## ################################################################# ##
  53.     ## Check for existence of the named chess directory
  54.     ## ################################################################# ##
  55.  
  56.     if (! (-d "$CHESSDIR")) {
  57.  
  58.     ## ############################################################# ##
  59.     ## Ask user for confirmation if attached to tty
  60.     ## ############################################################# ##
  61.  
  62.     if (-t) {
  63.         $old = select ;    ## Remember selected output
  64.         select(stdout) ;    ## Write to standard output
  65.         $| = 1 ;        ## Keep it flushed
  66.         printf("Chess directory <$CHESSDIR> does not exist.") ;
  67.         printf(" Create it? [y/q]: ");
  68.  
  69.         $_ = <tty> ;    ## Read response from tty
  70.         if (/^[qQ].*/) {
  71.         die "Bye!\n" ;    ## Quit if q selected
  72.         }
  73.  
  74.         select($old) ;    ## Re-select the old output
  75.     }
  76.  
  77.     ## ############################################################# ##
  78.     ## Create a chess directory or die
  79.     ## ############################################################# ##
  80.  
  81.     die "cmail: Can't create directory: $CHESSDIR\n"
  82.         unless mkdir("$CHESSDIR", 511) ;
  83.     printf("Created chess directory <$CHESSDIR>.\n") ;
  84.     printf("You can move it but remember to set the CMAIL_DIR") ;
  85.     printf(" environment variable.\n") ;
  86.     }
  87.  
  88.     ## ################################################################# ##
  89.     ## Change to the $CHESSDIR directory whether newly created or not
  90.     ## ################################################################# ##
  91.  
  92.     chdir "$CHESSDIR" ;
  93. }
  94. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  95.  
  96.  
  97. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  98. ## Parse command-line arguments
  99. sub parse_flags {
  100.     ## ################################################################# ##
  101.     ## Set up defaults from the environment or from hard-wired constants
  102.     ## ################################################################# ##
  103.  
  104.     $SHOWC       = 0 ;
  105.     $SHOWW       = 0 ;
  106.     $LOGFILE     = "&STDERR" ;
  107.     $MAILPROG    = $ENV{'CMAIL_MAILPROG'} ;
  108.     $MAILPROG    = "/usr/ucb/Mail" if (   (-x "/usr/ucb/Mail")
  109.                        && (! $MAILPROG)) ;
  110.     $MAILPROG    = "/usr/ucb/mail" if (   (-x "/usr/ucb/mail")
  111.                        && (! $MAILPROG)) ;
  112.     $MAILPROG    = "Mail" unless ($MAILPROG) ;
  113.     printf("\$CMAIL_DIR now obsolete. Use \$CHESSDIR instead.\n")
  114.     if ($ENV{'CMAIL_DIR'}) ;
  115.     $CHESSDIR     = $ENV{'CHESSDIR'} ;
  116.     $HOMEDIR     = $ENV{'HOME'} ;
  117.     $CHESSDIR     = "$HOMEDIR/Chess" unless ($CHESSDIR) ;
  118.     $CHESSDIR     = "~/Chess"        unless ($HOMEDIR) ;
  119.     $ALIAS_FILE     = $ENV{'CMAIL_ALIASES'} ;
  120.     $ALIAS_FILE     = ".cmailaliases" unless ($ALIAS_FILE) ;
  121.     $GAMES_FILE     = $ENV{'CMAIL_GAMES'} ;
  122.     $GAMES_FILE     = ".cmailgames" unless ($GAMES_FILE) ;
  123.     $TIME_DELAY     = $ENV{'CMAIL_TIME_DELAY'} ;
  124.     $TIME_DELAY     = 0 unless ($TIME_DELAY) ;
  125.     &get_pw_name() ;
  126.     $ME         = $PW_NAME ;
  127.     $ME         = $ENV{'LOGNAME'} unless ($ME) ;
  128.     $PGN_EVENT   = "Email correspondence game" ;
  129.     $PGN_SITE     = "NET";
  130.     $PGN_ROUND     = "-";
  131.     $PGN_WHITE     = "?";
  132.     $PGN_BLACK     = "?";
  133.     $PGN_WHITENA = "?";
  134.     $PGN_BLACKNA = "?";
  135.     $PGN_MODE    = "EM";
  136.     $SEND_MAIL   = 1 ;
  137.     $LOAD_XBOARD = 1 ;
  138.     $REUSE       = 1 ;
  139.     $TD_FLAGS    = " -td $TIME_DELAY" ;
  140.     $NCP_FLAGS   = " -ncp" ;
  141.  
  142.     ## ################################################################# ##
  143.     ## Define the usage string
  144.     ## ################################################################# ##
  145.  
  146.     $USAGE = ("cmail
  147.         [-h] [-c] [-w] [-[x]v] [-[x]mail] [-[x]xboard] [-[x]reuse] [-remail] 
  148.         [-game <name>] [-opp <name>] [-addr <address>] [-dir <directory>]
  149.         [-gamesFile <file>] [-aliasesFile <file>] [-logFile <file>]
  150.         [-event <event>] [-site <site>] [-round <round>] [-mode <mode>]
  151.         [-(white|black) <full name>] [-(white|black)na <email address>]
  152.         [-mailprog <mail program>]") ;
  153.  
  154.     ## ################################################################# ##
  155.     ## Overwrite defaults if specified on the command-line
  156.     ## ################################################################# ##
  157.  
  158.     $UNREC_ARGS = "" ;
  159.     while ($ARGV = shift) {
  160.     $UNREC = 0 if ($ARGV =~ /^-/) ;
  161.     if    ("$ARGV" eq "-h")          {die("Usage: $USAGE\n")      ;}
  162.     elsif ("$ARGV" eq "-c")          {$SHOWC       = 1            ;}
  163.     elsif ("$ARGV" eq "-w")          {$SHOWW       = 1            ;}
  164.     elsif ("$ARGV" eq "-v")          {$DEBUG       = 1            ;}
  165.     elsif ("$ARGV" eq "-xv")      {$DEBUG       = 0            ;
  166.                            $QUIET       = 1            ;}
  167.     elsif ("$ARGV" eq "-mail")      {$SEND_MAIL   = 1            ;}
  168.     elsif ("$ARGV" eq "-xmail")      {$SEND_MAIL   = 0            ;}
  169.     elsif ("$ARGV" eq "-xboard")      {$LOAD_XBOARD = 1            ;}
  170.     elsif ("$ARGV" eq "-xxboard")      {$LOAD_XBOARD = 0            ;}
  171.     elsif ("$ARGV" eq "-reuse")      {$REUSE       = 1            ;}
  172.     elsif ("$ARGV" eq "-xreuse")      {$REUSE       = 0            ;}
  173.     elsif ("$ARGV" eq "-remail")      {$LOAD_XBOARD = 0            ;
  174.                        $SEND_MAIL   = 1            ;}
  175.     elsif ("$ARGV" eq "-game")      {$PGN_GAME    = shift        ;}
  176.     elsif ("$ARGV" eq "-opp")      {$OPP_NAME    = shift        ;}
  177.     elsif ("$ARGV" eq "-addr")      {$OPP_ADDRESS = shift        ;}
  178.     elsif ("$ARGV" eq "-dir")      {$CHESSDIR    = shift        ;}
  179.     elsif ("$ARGV" eq "-mailprog")      {$MAILPROG    = shift        ;}
  180.     elsif ("$ARGV" eq "-gamesFile")   {$GAMES_FILE  = shift        ;}
  181.     elsif ("$ARGV" eq "-aliasesFile") {$ALIAS_FILE  = shift        ;}
  182.     elsif ("$ARGV" eq "-logFile")     {$LOGFILE     = shift        ;}
  183.     elsif ("$ARGV" =~ /^-(td|timeDelay)$/)
  184.                                       {$TD_FLAGS    = (  " $ARGV "
  185.                                . shift)    ;}
  186.     elsif ("$ARGV" =~ /^-noChessComputer$/)
  187.                                       {$NCP_FLAGS   = (  " $ARGV "
  188.                                . shift)    ;}
  189.     elsif ("$ARGV" =~ /^-[x]?ncp$/)      {$NCP_FLAGS    = " $ARGV"     ;}
  190.     elsif ("$ARGV" eq "-event")      {$PGN_EVENT    = shift           ;}
  191.     elsif ("$ARGV" eq "-site")      {$PGN_SITE    = shift           ;}
  192.     elsif ("$ARGV" eq "-round")      {$PGN_ROUND    = shift           ;}
  193.     elsif ("$ARGV" eq "-white")      {$PGN_WHITE    = shift           ;}
  194.     elsif ("$ARGV" eq "-black")      {$PGN_BLACK    = shift           ;}
  195.     elsif ("$ARGV" eq "-whitena")      {$PGN_WHITENA    = shift           ;}
  196.     elsif ("$ARGV" eq "-blackna")      {$PGN_BLACKNA    = shift           ;}
  197.     elsif ("$ARGV" eq "-mode")      {$PGN_MODE    = shift           ;}
  198.     elsif ("$ARGV" =~ /^-[x]?oldsave$/)
  199.                                       {$SAVE_FLAGS    = " $ARGV"     ;}
  200.     elsif ("$ARGV" eq "-oldSaveStyle"){$SAVE_FLAGS    = (  " $ARGV "
  201.                                . shift)    ;}
  202.     elsif ("$ARGV" =~ /^-/ || $UNREC) {
  203.         $UNREC_ARGS .= " " . $ARGV ;
  204.         $UNREC = 1 ;
  205.     } else {
  206.         die("cmail: Unrecognised flag \"$ARGV\"\nUsage: $USAGE\n") ;
  207.     }
  208.     }
  209.  
  210.     $ENV{'CMAIL_MAILPROG'} = $MAILPROG ; ## Propagate to cmail grandchild
  211.     $OLDSAVE = (   $SAVE_FLAGS
  212.         =~ /^ (-oldsave|-oldSaveStyle [Tt][Rr][Uu][Ee])$/) ;
  213. }
  214. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  215.  
  216.  
  217. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  218. ## Initialisation of variables and environment
  219. sub showGPL {
  220.     ## ################################################################# ##
  221.     ## Show copyright notice
  222.     ## ################################################################# ##
  223.  
  224.     while(<DATA>) {
  225.     last if(/^{END OF GPL COPYRIGHT}$/) ;
  226.     $_ =~ s/\$Revision[:] (.*) \$/$1/ ;
  227.     print ;
  228.     }
  229.  
  230.     ## ################################################################# ##
  231.     ## Show conditions if requested
  232.     ## ################################################################# ##
  233.  
  234.     while(<DATA>) {
  235.     last if(/^{END OF GPL CONDITIONS}$/) ;
  236.     if($SHOWW) {
  237.         print ;
  238.     }
  239.     }
  240.  
  241.     ## ################################################################# ##
  242.     ## Show warranty if requested
  243.     ## ################################################################# ##
  244.  
  245.     if ($SHOWC) {
  246.     if($SHOWW) {
  247.         printf("\n") ;
  248.     }
  249.     while(<DATA>) {
  250.         print ;
  251.     }
  252.     }
  253.  
  254.     if ($SHOWC || $SHOWW) {
  255.     exit ;            ## Abort if showed conditions or warranty
  256.     }
  257. }
  258. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  259.  
  260.  
  261. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  262. ## Initialisation of variables and environment
  263. sub initialise {
  264.     $FLIP = "false" ;        ## The board is not flipped by default
  265.  
  266.     &parse_flags(@ARGV) ;    ## Parse command-line arguments
  267.  
  268.     &showGPL unless $QUIET ;
  269.  
  270.     open(tty, "< /dev/tty") ;    ## Open tty for reading
  271.  
  272.     &need_chess_dir() ;        ## Check for the existence of CHESSDIR
  273.  
  274.     if ($DEBUG) {
  275.     open (logfile, ">$LOGFILE") ; ## Default is STDERR
  276.     }
  277.  
  278.     &debug("Called <initialise>\n") ;
  279. }
  280. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  281.  
  282.  
  283. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  284. ## Prompt for a game name, if <cr> use a default
  285. sub prompt_for_game_name {
  286.     &debug("Called <prompt_for_game_name>\n") ;
  287.     $old = select ;        ## Remember the selected output
  288.     select(stdout);        ## Diagnostics go to logfile
  289.     $| = 1 ;            ## Keep it flushed
  290.  
  291.     printf("Game name [<cr> to use default]: ") ;
  292.     die "cmail: tty not open\n" unless (-t) ;
  293.     <tty> =~ /(.*)/ ;        ## Read line from tty
  294.     $PGN_GAME = "$1" ;        ## Assign to game name
  295.  
  296.     select($old) ;        ## Re-select the old output
  297. }
  298. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  299.  
  300.  
  301. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  302. ## Get opponent's address
  303. sub find_opp_address_in_game_file {
  304.     &debug("Called <find_opp_address_in_game_file> game name",
  305.        " <$PGN_GAME>\n") ;
  306.     if (! ("" eq "$PGN_GAME")) { ## Can't find it without the game name
  307.     ## ############################################################# ##
  308.     ## Open the game file and read all the entries
  309.     ## ############################################################# ##
  310.  
  311.     if (open(GAMES_IN, "<$GAMES_FILE")) {
  312.         while(<GAMES_IN>) {
  313.         if (/^<$PGN_GAME>\s*(.*)\s*$/) {    ## Match!
  314.             $OPP_ADDRESS = $1 ;    ## Found opponent's address
  315.         }
  316.         }
  317.  
  318.         if ("" eq $OPP_ADDRESS) {
  319.         $SAVE_ADDRESS = 1 ; ## Save the address when it is found
  320.         }
  321.  
  322.     } else {        ## Game file doesn't exist yet
  323.         $SAVE_ADDRESS = 1 ;    ## Save the address when it is found
  324.     }
  325.     }
  326. }
  327. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  328.  
  329.  
  330. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  331. ## Get game name from game file
  332. sub find_game_in_game_file {
  333.     &debug("Called <find_game_in_game_file> opp address",
  334.        " <$OPP_ADDRESS>\n") ;
  335.     if ("" ne "$OPP_ADDRESS") { ## Can't find it without the opp address
  336.  
  337.     ## ############################################################# ##
  338.     ## Open the game file and read all the entries
  339.     ## ############################################################# ##
  340.  
  341.     if (open(GAMES_IN, "< $GAMES_FILE")) {
  342.         while(<GAMES_IN>) {
  343.         if ($_ =~ /^<(.*)>\s*$OPP_ADDRESS\s*$/) {
  344.             $PGN_GAME = $1 ; ## Match!
  345.         }
  346.         }
  347.     } else {
  348.         $SAVE_ADDRESS = 1 ; ## Save the address when it is found
  349.         $PGN_GAME     = "$ME-VS-$OPP_NAME" ; ## Construct default name
  350.     }
  351.     }
  352.     ## ################################################################# ##
  353.     ## Failed to find the game name so construct a default from players
  354.     ## ################################################################# ##
  355.  
  356.     if ("" eq $PGN_GAME) {
  357.     $SAVE_ADDRESS = 1 ;    ## Save the address when it is found
  358.     $PGN_GAME     = "$ME-VS-$OPP_NAME" ; ## Construct default name
  359.     }
  360. }
  361. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  362.  
  363.  
  364. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  365. ## Prompt for opponent's address
  366. sub prompt_for_opp_address {
  367.     &debug("Called <prompt_for_opp_address>\n") ;
  368.  
  369.     ## ################################################################# ##
  370.     ## Prompt for opponent's email address
  371.     ## ################################################################# ##
  372.  
  373.     printf("Opponent's email address: ") ;
  374.     die "cmail: tty not open\n" unless (-t) ;
  375.     <tty> =~ /(.*)/ ;
  376.     $OPP_ADDRESS = $1 ;
  377.  
  378.     ## ################################################################# ##
  379.     ## Use name as default if still blank
  380.     ## ################################################################# ##
  381.  
  382.     if ("" eq $OPP_ADDRESS) {
  383.     $OPP_ADDRESS = $OPP_NAME ;
  384.     }
  385.  
  386.     ## ################################################################# ##
  387.     ## Add the alias to the alias file
  388.     ## ################################################################# ##
  389.  
  390.     if ($ADD_ALIAS == 1) {
  391.     printf("Adding alias <$OPP_NAME = $OPP_ADDRESS>.\n") ;
  392.     die "cmail: Can't open file: $ALIAS_FILE\n"
  393.         unless open(ALIASES_OUT, ">> $ALIAS_FILE") ;
  394.     select(ALIASES_OUT) ;
  395.     printf("$OPP_NAME\t=\t$OPP_ADDRESS\n") ;
  396.     close(ALIASES_OUT) ;
  397.     select(stdout) ;
  398.     }
  399. }
  400. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  401.  
  402.  
  403. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  404. ## Prompt for opponent's name
  405. sub prompt_for_opp_name {
  406.     &debug("Called <prompt_for_opp_name>\n") ;
  407.     $old = select ;        ## Remember the selected output
  408.     select(stdout) ;        ## Write to stdout
  409.     $| = 1 ;            ## Keep it flushed
  410.     printf("Opponent's name: ") ;
  411.  
  412.     die "cmail: tty not open\n" unless (-t) ; ## Check tty is open
  413.     <tty> =~ /(.*)/ ;        ## Read line from tty
  414.     $OPP_NAME = $1 ;        ## Match!
  415.     die "cmail: I can't proceed without the opponent's name.\n"
  416.     unless ($OPP_NAME) ;
  417.  
  418.     select($old) ;        ## Re-select the old output
  419. }
  420. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  421.  
  422.  
  423. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  424. ## Search for opponent's name in alias file if it exists
  425. sub find_opp_address_in_alias_file {
  426.     &debug("Called <find_opp_address_in_alias_file> opp name <$OPP_NAME>\n") ;
  427.  
  428.     ## ################################################################# ##
  429.     ## Check the alias file exists
  430.     ## ################################################################# ##
  431.  
  432.     if (-f "$ALIAS_FILE") {
  433.     ## ############################################################# ##
  434.     ## Open alias file and read all the entries
  435.     ## ############################################################# ##
  436.  
  437.     die "cmail: Can't open file: $ALIAS_FILE\n"
  438.         unless open(ALIASES_IN, "< $ALIAS_FILE") ;
  439.     while (<ALIASES_IN>) {
  440.         if (/$OPP_NAME\s*=\s*(.*)/) {
  441.         $OPP_ADDRESS = $1 ; ## Match!
  442.         }
  443.     }
  444.  
  445.     ## ############################################################# ##
  446.     ## Check if we should save the new address in the alias file
  447.     ## ############################################################# ##
  448.  
  449.     if ("" eq $OPP_ADDRESS) {
  450.         $ADD_ALIAS = 1 ;    ## Remember to add new alias to alias file
  451.     }
  452.  
  453.     close(ALIASES_IN) ;    ## Close alias in file
  454.     } else {
  455.     $ADD_ALIAS = 1 ;    ## Remember to add new alias to alias file
  456.     }
  457. }
  458. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  459.  
  460.  
  461. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  462. ## Add this game to the list of games in the game file
  463. sub add_game_to_game_file {
  464.     &debug("Called <add_game_to_game_file>\n") ;
  465.  
  466.     ## ################################################################# ##
  467.     ## Append address to game file
  468.     ## ################################################################# ##
  469.  
  470.     if ($SAVE_ADDRESS) {
  471.     die "cmail: Can't open file: $GAMES_FILE\n" ## Open the file or die
  472.         unless open(GAMES_OUT, ">> $GAMES_FILE") ;
  473.     select(GAMES_OUT) ;    ## Write to games file
  474.     printf("<$PGN_GAME> $OPP_ADDRESS\n") ;    ## Make the entry
  475.     close(GAMES_OUT) ;    ## Close games file
  476.     }
  477.  
  478.     select(STDOUT) ;        ## Re-select STDOUT
  479. }
  480. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-#
  481.  
  482.  
  483. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  484. ## Load the game
  485. sub play_game {
  486.     &debug("Called <play_game>\n") ;
  487.     $| = 1 ;            ## Start flushing output buffer
  488.  
  489.     ## ################################################################# ##
  490.     ## Load xboard unless inhibited by command-line arguments
  491.     ## ################################################################# ##
  492.  
  493.     if ($LOAD_XBOARD) {
  494.     ## ############################################################# ##
  495.     ## Remove output files from previous run
  496.     ## ############################################################# ##
  497.  
  498.     unlink("$PGN_GAME.pos.out") ;
  499.     unlink("$PGN_GAME.game.out") ;
  500.  
  501.     ## ############################################################# ##
  502.     ## Invoke xboard with loads of flags
  503.     ## ############################################################# ##
  504.  
  505.     $LOG_FILE = "$PGN_GAME.log" ;
  506.     $XBOARD_ARGS = (  " -cmail $PGN_GAME"
  507.             . " -flipView $FLIP"
  508.             . "$SAVE_FLAGS"
  509.             . "$TD_FLAGS"
  510.             . "$NCP_FLAGS"
  511.             . "$UNREC_ARGS") ;
  512.     &debug("Invoking xboard with args:$XBOARD_ARGS\n") ;
  513.     $PID_FILE = "$PGN_GAME.pid" ;
  514.     if (   (! $REUSE)
  515.         || (! (   (-f $PID_FILE)
  516.            && ($XBOARD_PID = `cat $PID_FILE`)
  517.            && ("$XBOARD_PID" =~ /^\d+$/)
  518.            && (kill "SIGUSR1", $XBOARD_PID)))) {
  519.         printf("Loading xboard for game <$PGN_GAME>...") ;
  520.         system(  "{ ({ xboard $XBOARD_ARGS & } ;"
  521.            . "   echo \$! > $PID_FILE ;"
  522.            . "   wait ;"
  523.            . "   rm $PID_FILE) & } >$LOG_FILE 2>&1") ;
  524.         printf(  "done.\n"
  525.            . "If nothing happens look for an error message in\n"
  526.            . "$CHESSDIR/$LOG_FILE.\n") ;
  527.     } else {
  528.         printf("Revived existing xboard for game <$PGN_GAME>.\n"
  529.            . "If nothing happens"
  530.            . " remove $CHESSDIR/$PID_FILE and try again.\n") ;
  531.     }
  532.     exit 0 ;
  533.     }
  534. }
  535. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  536.  
  537.  
  538. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  539. ## Find the game the user wants by any means possible
  540. sub find_game {
  541.     &debug("Called <find_game>\n") ;
  542.  
  543.     ## ################################################################# ##
  544.     ## Ask user for a game name if not already known
  545.     ## ################################################################# ##
  546.  
  547.     if ("" eq "$PGN_GAME") {
  548.     &prompt_for_game_name() ;
  549.     }
  550.  
  551.     ## ################################################################# ##
  552.     ## Find out opponent's details
  553.     ## ################################################################# ##
  554.  
  555.     if ("" eq "$PGN_GAME") {
  556.     if ("" eq "$OPP_NAME") {
  557.         &prompt_for_opp_name() ; ## Ask user for opponent's name
  558.     }
  559.     &find_opp_address_in_alias_file() ; ## Find opp address in aliases
  560.     &find_game_in_game_file() ; ## Find game name in game file
  561.     } else {
  562.     &find_opp_address_in_game_file() ; ## Find opp address in game file
  563.     if ("" eq "$OPP_ADDRESS") {
  564.         $OPP_ADDRESS = $RETURN_ADDRESS ; ## Use return address instead
  565.         &debug(  "Using return address <$OPP_ADDRESS>"
  566.            . " for opponent address\n") ;
  567.     }
  568.     if (("" eq "$OPP_ADDRESS") && ("" eq "$OPP_NAME")) {
  569.         &prompt_for_opp_name() ; ## Ask user for opponent's name
  570.     }
  571.     }
  572.  
  573.     ## ################################################################# ##
  574.     ## Finally ask user for missing details as a last resort
  575.     ## ################################################################# ##
  576.  
  577.     if ("" eq "$OPP_ADDRESS") {
  578.     &find_opp_address_in_alias_file() ; ## Find opp address in aliases
  579.     if ("" eq "$OPP_ADDRESS") {
  580.         &prompt_for_opp_address() ;    ## Ask user for opponent's address
  581.     }
  582.     }
  583.  
  584.     ## ################################################################# ##
  585.     ## If no $PGN_GAME.game.in file, assume we're starting a new game
  586.     ## ################################################################# ##
  587.  
  588.     if (! (-f "$PGN_GAME.game.in")) {
  589.     &start_new_game() ;
  590.     }
  591.  
  592.     ## ################################################################# ##
  593.     ## Give up if we haven't got anywhere to send a move to
  594.     ## ################################################################# ##
  595.  
  596.     if ("" eq "$OPP_ADDRESS") {
  597.     die "cmail: Can't proceed without opponent's email address.\n" ;
  598.     }
  599. }
  600. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  601.  
  602.  
  603. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  604. ## Get the date
  605. sub get_date {
  606.     $the_time = time ;
  607.     ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) =
  608.     localtime($the_time) ;
  609.     $mon ++ ;
  610.     if ($mon < 10) {
  611.     $mon = "0$mon" ;
  612.     }
  613.     if ($year < 94) {
  614.     $century = 20 ;
  615.     } else {
  616.     $century = 19 ;
  617.     }
  618.     "$century$year.$mon.$mday" ;
  619. }
  620. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  621.  
  622.  
  623. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  624. ## Start a new game
  625. sub start_new_game {
  626.     printf("Starting a new game.\n") ;
  627.     $TO_PLAY = "white" ;
  628.     $MOVENUM = 0 ;
  629.  
  630.     ## ################################################################# ##
  631.     ## Create an empty game file
  632.     ## ################################################################# ##
  633.  
  634.     open(GAMEFILE, "> $PGN_GAME.game.in") ;
  635.     select(GAMEFILE) ;
  636.     if ($OLDSAVE) {
  637.     printf("# xboard game file\n\n        algebraic\n") ;
  638.     } else {            ## New PGN format
  639.     &get_pw_name() ;
  640.     &get_pw_gcos() ;
  641.     $PGN_WHITE   = $PW_GCOS ;
  642.     $PGN_WHITE   = "?" unless ($PGN_WHITE) ;
  643.     $PGN_BLACK   = "?" unless ($PGN_BLACK) ;
  644.     $PGN_WHITENA = "$PW_NAME@" . `domainname` if ($PGN_WHITENA eq "?") ;
  645.     $PGN_WHITENA =~ s/\n// ;
  646.     $PGN_WHITENA = "?" if ($PGN_WHITENA =~ /(^@)|(@$)/) ;
  647.     $PGN_BLACKNA = $OPP_ADDRESS if ($PGN_BLACKNA eq "?");
  648.     $PGN_BLACKNA = "?" unless ($PGN_BLACKNA) ;
  649.     $PGN_DATE    = &get_date() ;
  650.     $PGN_DATE    = "?" unless ($PGN_DATE) ;
  651.     printf("[Event \"$PGN_EVENT\"]
  652. [Site \"$PGN_SITE\"]
  653. [Date \"$PGN_DATE\"]
  654. [Round \"$PGN_ROUND\"]
  655. [White \"$PGN_WHITE\"]
  656. [Black \"$PGN_BLACK\"]
  657. [Result \"*\"]
  658. [WhiteNA \"$PGN_WHITENA\"]
  659. [BlackNA \"$PGN_BLACKNA\"]
  660. [Mode \"$PGN_MODE\"]
  661. [CmailGameName \"$PGN_GAME\"]
  662.  
  663. *
  664. ") ;
  665.     }
  666.     close(GAMEFILE) ;
  667. }
  668. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  669.  
  670.  
  671. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  672. ## Get the password file gcos (full name) entry
  673. sub get_pw_entry {
  674.     ($name, $passwd, $uid, $gid, $quota, $comment, $gcos, $dir, $shell) =
  675.     getpwuid($<);
  676.     ($name, $gcos) ;
  677. }
  678. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  679.  
  680.  
  681. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  682. ## Get password file gcos (full name) entry
  683. sub get_pw_gcos {
  684.     if (! $PW_GCOS) {
  685.     ($dummy, $PW_GCOS) = &get_pw_entry() ;
  686.     $PW_GCOS =~ s/^\s*([^,()]+[^ ,()])[ ]*[,()].*$/$1/;
  687.     if ($PW_GCOS =~ /^([^,()]+)\s+([^\s,()]+)$/) { ## Multi-word name
  688.         $PW_GCOS = $2 . ", " . $1 ;
  689.     } elsif ($PW_GCOS !~ /^([^\s,()]+)/) { ## No sensible gcos entry 
  690.         $PW_GCOS = "" ;
  691.     }                ## Else leave it as one word
  692.     &debug("PW full name is <$PW_GCOS>\n");
  693.     }
  694. }
  695. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  696.  
  697.  
  698. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  699. ## Get password file user name entry
  700. sub get_pw_name {
  701.     if (! $PW_NAME) {
  702.     ($PW_NAME, $dummy) = &get_pw_entry() ;
  703.     &debug("PW name is $PW_NAME\n");
  704.     }
  705. }
  706. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  707.  
  708.  
  709. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  710. ## Analyse the email message
  711. sub analyse_email_message {
  712.     printf("Processing game message...") ;
  713.  
  714.     ## ################################################################# ##
  715.     ## Parse the mail message
  716.     ## ################################################################# ##
  717.  
  718.     while(<stdin>) {
  719.     if (/^From:?.*[<\s]([^<\s]+@[^>\s]+)([\s>]|$)/) {
  720.         $RETURN_ADDRESS = $1 ; ## Default for opponent's email address
  721.         &debug("Found opponent's email address <$RETURN_ADDRESS>\n") ;
  722.     } elsif(/^Subject:\s*cmail\s*(\d+)[.]\s+(.*)\s*<(.*)>$/) {
  723.         &debug("Move is $1 according to subject line\n") ;
  724.         $PGN_GAME = $3 ;
  725.         &debug("Found game name <$PGN_GAME>\n") ;
  726.         if (($1 eq 1) && ($2 =~ /^[^.]/)) {
  727.         $SAVE_ADDRESS = 1 ; ## Save address if on black's first move
  728.         }
  729.     } elsif(/xboard position file/) {
  730.         &debug("Found xboard position file\n") ; ## Don't need to read
  731.         $SAVE_FLAGS = " -oldsave" ; ## Old save-style format
  732.         $OLDSAVE    = 1 ;
  733.     } elsif(/^(black|white) to play$/) {
  734.         $TO_PLAY = $1 ;     ## Whose move is it (colour)?
  735.         if ($TO_PLAY eq "black") {
  736.         $FLIP = "true" ; ## Flip xboard board if black to play
  737.         }
  738.         &debug("Found to play <$TO_PLAY>, flip is <$FLIP>\n") ;
  739.     } elsif(   /xboard game file/            ## Old xboard format
  740.         || (   (! ($IN_FILE || $STORING))
  741.             && /^(\[.*\]|\{.*)/)) {      ## PGN format
  742.         ## ######################################################### ##
  743.         ## Open game file for copying the rest of the mail message into
  744.         ## ######################################################### ##
  745.  
  746.         if ($PGN_GAME) {
  747.         $IN_FILE = 1 ;
  748.         die "cmail: Can't open file: $PGN_GAME.game.in\n"
  749.             unless open(GAMEFILE, "> $PGN_GAME.game.in") ;
  750.         select(GAMEFILE) ;
  751.         } else {
  752.         $STORING = 1 ;
  753.         }
  754.         &debug("Found xboard game file\n") ;
  755.     } elsif((/^\[Black "[?]"\]/) && ($SAVE_ADDRESS)) {
  756.         &get_pw_gcos() ;
  757.         $PW_GCOS = "$RETURN_ADDRESS" unless ($PW_GCOS) ;
  758.         $PW_GCOS = "?" unless ($PW_GCOS) ;
  759.         $_ = "[Black \"$PW_GCOS\"]\n" ;
  760.         &debug("Changed Black tag to be $_") ;
  761.     } elsif(   (/^\[WhiteNA "[?]"\]/)
  762.         && (($SAVE_ADDRESS) && ($RETURN_ADDRESS))) {
  763.         $_ = "[WhiteNA \"$RETURN_ADDRESS\"]\n" ;
  764.         &debug("Changed WhiteNA tag to be $_") ;
  765.     } elsif(   (/^\[WhiteNA "(.*)"\]/)
  766.         && ("$PGN_WHITENA" eq "?")) {
  767.         $PGN_WHITENA = $1 ;
  768.         &debug("Found WhiteNA tag to be \"$PGN_WHITENA\"\n") ;
  769.     } elsif(   (/^\[BlackNA "(.*)"\]/)
  770.         && ("$PGN_BLACKNA" eq "?")) {
  771.         $PGN_BLACKNA = $1 ;
  772.         &debug("Found BlackNA tag to be \"$PGN_BLACKNA\"\n") ;
  773.     } elsif(/^\[CmailGameName "(.*)"\]/) {
  774.         $PGN_GAME = "$1" ;
  775.         &debug("Found cmail game name from PGN tag \"$PGN_GAME\"\n") ;
  776.         if ($STORING) {
  777.         $IN_FILE = 1 ;
  778.         $STORING = 0 ;
  779.         die "cmail: Can't open file: $PGN_GAME.game.in\n"
  780.             unless open(GAMEFILE, "> $PGN_GAME.game.in") ;
  781.         select(GAMEFILE) ;
  782.         print "$STORE" ;
  783.         }
  784.     } elsif (/^(.*[^\d]+|)\d+[.]\s*([^\s*]*\s+|)[^\s.*]+(\s*\d+[.]\s*|)[\s*]*$/) {
  785.         if ($2) {
  786.         $TO_PLAY = "white" ;
  787.         } else {
  788.         $TO_PLAY = "black" ;
  789.         }
  790.         &debug("$TO_PLAY to play\n") ;
  791.     }
  792.     if ($IN_FILE) {
  793.         &debug("$_") ;
  794.         print ;        ## Copy end of mail message into game file
  795.     }
  796.     if ($STORING) {
  797.         &debug("$_") ;
  798.         $STORE .= $_ ;    ## Add line to store
  799.     }
  800.     }
  801.     die "cmail: Couldn't find cmail game name!\n" if ($STORING) ;
  802.     if (! $RETURN_ADDRESS) {
  803.     if ($TO_PLAY eq "black") {
  804.         $RETURN_ADDRESS = $PGN_WHITENA unless ("$PGN_WHITENA" eq "?") ;
  805.     } else {
  806.         $RETURN_ADDRESS = $PGN_BLACKNA unless ("$PGN_BLACKNA" eq "?") ;
  807.     }
  808.     }
  809.     close(GAMEFILE) ;
  810.     select(STDOUT) ;
  811.     printf("done.\n") ;
  812.  
  813.     ## ################################################################# ##
  814.     ## Check that we have enough info about the players to continue
  815.     ## ################################################################# ##
  816.  
  817.     &find_game() ;
  818. }
  819. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  820.  
  821.  
  822. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  823. ## Analyse output files and send the move
  824. sub send_move {
  825.     ## ################################################################# ##
  826.     ## Process the game.out and pos.out (if there is one) files
  827.     ## ################################################################# ##
  828.  
  829.     die "cmail: Can't open file: $PGN_GAME.out\n"
  830.     unless open(out, "> $PGN_GAME.out") ;
  831.     select(out) ;
  832.     
  833.     ## ################################################################# ##
  834.     ## Cat the pos file into the .out file if there is one (old-style)
  835.     ## ################################################################# ##
  836.  
  837.     if (open(pos, "< $PGN_GAME.pos.out")) {
  838.     printf("cmail game <$PGN_GAME>\n") ; ## Old-style format
  839.  
  840.     while(<pos>) {
  841.         &debug("$_") ;
  842.         
  843.         ## ######################################################### ##
  844.         ## We probably don't know who it is to play if we bypassed
  845.         ## loading xboard (for remail) so derive it from the
  846.         ## "to play" line in the pos.out file
  847.         ## ######################################################### ##
  848.  
  849.         if (/^(black|white) to play$/) {
  850.         if ($1 eq "black") {
  851.             $TO_PLAY = "white" ; ## Change black to white
  852.         } else {
  853.             $TO_PLAY = "black" ; ## Change white to black
  854.         }
  855.         &debug("Found <$1> to play in",
  856.                " <$PGN_GAME.pos.out>,",
  857.                " reversed for remailing <$TO_PLAY>\n") ;
  858.         }
  859.         
  860.         print ;        ## Write the line to the .out file
  861.     }
  862.     close(pos) ;    ## Close the pos.out file
  863.     }
  864.     
  865.     ## ################################################################# ##
  866.     ## Cat the game file into the .out file. There must be one!
  867.     ## ################################################################# ##
  868.  
  869.     if (open(game, "< $PGN_GAME.game.out")) {
  870.     ## ############################################################# ##
  871.     ## Cat the .game.out file into the .out file, remembering
  872.     ## the move number of the last line
  873.     ## ############################################################# ##
  874.  
  875.     while(<game>) {
  876.         &debug("$_") ;
  877.         if ($_ =~ /^(.*[^\d]+|)(\d+)[.]+\s*[^\s.]*\s+(\S+)\s*$/) {
  878.         $MOVENUM = $2 ;
  879.         $MOVE    = $3 ;
  880.         }
  881.  
  882.         ## ######################################################### ##
  883.         ## We probably don't know who it is to play if we bypassed
  884.         ## loading xboard (for remail) and there is no position 
  885.         ## file (new-style), so derive it from the "to play" line 
  886.         ## in the game.out file
  887.         ## ######################################################### ##
  888.  
  889.         if (/^(black|white) to play$/) {
  890.         if ($1 eq "black") {
  891.             $TO_PLAY = "white" ; ## Change black to white
  892.         } else {
  893.             $TO_PLAY = "black" ; ## Change white to black
  894.         }
  895.         &debug("Found <$1> to play in",
  896.                " <$PGN_GAME.game.out>,",
  897.                " reversed for remailing <$TO_PLAY>\n") ;
  898.         }
  899.         print ;
  900.     }
  901.     close(game) ;        ## Close the game.out file
  902.     close(out) ;        ## Close the .out file
  903.     select(STDOUT) ;    ## Write to the standard output
  904.     
  905.     ## ############################################################# ##
  906.     ## If it's black to play, the subject line of the outgoing
  907.     ## mail message contains dots where the white move would
  908.     ## normally be
  909.     ## ############################################################# ##
  910.     
  911.     if ($TO_PLAY eq "black") {
  912.         $DOTS = " ...." ;
  913.     } else {
  914.         $DOTS = "" ;
  915.     }
  916.     
  917.     ## ############################################################# ##
  918.     ## Send the mail message to opponent's address unless bypassed
  919.     ## ############################################################# ##
  920.     
  921.     if ($SEND_MAIL) {
  922.         $| = 1 ;        ## Keep it flushed
  923.         print "" ;
  924.         $RES = system(  "$MAILPROG"
  925.               . " -s \"cmail $MOVENUM.$DOTS $MOVE <$PGN_GAME>\""
  926.               . " $OPP_ADDRESS < $PGN_GAME.out") ;
  927.         if ($RES / 256) {
  928.         printf(  "Failed to send email message.\n") ;
  929.         } else {
  930.         printf(  "Emailed move to <$OPP_ADDRESS>: $MOVENUM.$DOTS"
  931.                . " $MOVE <$PGN_GAME>\n") ;
  932.         }
  933.     } else {
  934.         printf("Email not sent (as requested).\n") ;
  935.         printf("Would have emailed move to <$OPP_ADDRESS>:") ;
  936.         printf(" $MOVENUM.$DOTS $MOVE <$PGN_GAME>\n") ;
  937.     }
  938.     } else {
  939.     printf("I can't find the game file.") ;
  940.     printf(" Did you save the game?\n") ;
  941.     printf("Email not sent\n") ;
  942.     }
  943. }
  944. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  945.  
  946.  
  947. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  948. ## Main body
  949.  
  950. &initialise() ;            ## Initialise variables etc.
  951.  
  952. if (-t) { ## No input directed (invoked from a shell rather than a mailer)
  953.     &debug("Interactive!\n") ;
  954.     &find_game() ;        ## Get the necessary info about the game
  955. } else {
  956.     &debug("Piping!\n") ;
  957.     &analyse_email_message() ;    ## Analyse the mail message
  958. }
  959.  
  960. &add_game_to_game_file() ;    ## Create an entry in user's list of games
  961.  
  962. &play_game() ;                  ## Load the game
  963.  
  964. &send_move() ;                  ## Analyse output files and send the move
  965.  
  966. close(tty) ;            ## Tidy up
  967. if ($DEBUG) {
  968.     close (logfile) ;        ## Tidy up
  969. }
  970. #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=#
  971. __END__
  972. cmail $Revision: 2.10 $, Copyright (C) 1993 Free Software Foundation, Inc.
  973. cmail comes with ABSOLUTELY NO WARRANTY; for details type `cmail -w'.
  974. cmail is free software, and you are welcome to redistribute it
  975. under certain conditions; type `cmail -c' for details.
  976.  
  977. {END OF GPL COPYRIGHT}
  978.             GNU GENERAL PUBLIC LICENSE
  979.    TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  980.  
  981.   0. This License applies to any program or other work which contains
  982. a notice placed by the copyright holder saying it may be distributed
  983. under the terms of this General Public License.  The "Program", below,
  984. refers to any such program or work, and a "work based on the Program"
  985. means either the Program or any derivative work under copyright law:
  986. that is to say, a work containing the Program or a portion of it,
  987. either verbatim or with modifications and/or translated into another
  988. language.  (Hereinafter, translation is included without limitation in
  989. the term "modification".)  Each licensee is addressed as "you".
  990.  
  991. Activities other than copying, distribution and modification are not
  992. covered by this License; they are outside its scope.  The act of
  993. running the Program is not restricted, and the output from the Program
  994. is covered only if its contents constitute a work based on the
  995. Program (independent of having been made by running the Program).
  996. Whether that is true depends on what the Program does.
  997.  
  998.   1. You may copy and distribute verbatim copies of the Program's
  999. source code as you receive it, in any medium, provided that you
  1000. conspicuously and appropriately publish on each copy an appropriate
  1001. copyright notice and disclaimer of warranty; keep intact all the
  1002. notices that refer to this License and to the absence of any warranty;
  1003. and give any other recipients of the Program a copy of this License
  1004. along with the Program.
  1005.  
  1006. You may charge a fee for the physical act of transferring a copy, and
  1007. you may at your option offer warranty protection in exchange for a fee.
  1008.  
  1009.   2. You may modify your copy or copies of the Program or any portion
  1010. of it, thus forming a work based on the Program, and copy and
  1011. distribute such modifications or work under the terms of Section 1
  1012. above, provided that you also meet all of these conditions:
  1013.  
  1014.     a) You must cause the modified files to carry prominent notices
  1015.     stating that you changed the files and the date of any change.
  1016.  
  1017.     b) You must cause any work that you distribute or publish, that in
  1018.     whole or in part contains or is derived from the Program or any
  1019.     part thereof, to be licensed as a whole at no charge to all third
  1020.     parties under the terms of this License.
  1021.  
  1022.     c) If the modified program normally reads commands interactively
  1023.     when run, you must cause it, when started running for such
  1024.     interactive use in the most ordinary way, to print or display an
  1025.     announcement including an appropriate copyright notice and a
  1026.     notice that there is no warranty (or else, saying that you provide
  1027.     a warranty) and that users may redistribute the program under
  1028.     these conditions, and telling the user how to view a copy of this
  1029.     License.  (Exception: if the Program itself is interactive but
  1030.     does not normally print such an announcement, your work based on
  1031.     the Program is not required to print an announcement.)
  1032.  
  1033. These requirements apply to the modified work as a whole.  If
  1034. identifiable sections of that work are not derived from the Program,
  1035. and can be reasonably considered independent and separate works in
  1036. themselves, then this License, and its terms, do not apply to those
  1037. sections when you distribute them as separate works.  But when you
  1038. distribute the same sections as part of a whole which is a work based
  1039. on the Program, the distribution of the whole must be on the terms of
  1040. this License, whose permissions for other licensees extend to the
  1041. entire whole, and thus to each and every part regardless of who wrote it.
  1042.  
  1043. Thus, it is not the intent of this section to claim rights or contest
  1044. your rights to work written entirely by you; rather, the intent is to
  1045. exercise the right to control the distribution of derivative or
  1046. collective works based on the Program.
  1047.  
  1048. In addition, mere aggregation of another work not based on the Program
  1049. with the Program (or with a work based on the Program) on a volume of
  1050. a storage or distribution medium does not bring the other work under
  1051. the scope of this License.
  1052.  
  1053.   3. You may copy and distribute the Program (or a work based on it,
  1054. under Section 2) in object code or executable form under the terms of
  1055. Sections 1 and 2 above provided that you also do one of the following:
  1056.  
  1057.     a) Accompany it with the complete corresponding machine-readable
  1058.     source code, which must be distributed under the terms of Sections
  1059.     1 and 2 above on a medium customarily used for software interchange; or,
  1060.  
  1061.     b) Accompany it with a written offer, valid for at least three
  1062.     years, to give any third party, for a charge no more than your
  1063.     cost of physically performing source distribution, a complete
  1064.     machine-readable copy of the corresponding source code, to be
  1065.     distributed under the terms of Sections 1 and 2 above on a medium
  1066.     customarily used for software interchange; or,
  1067.  
  1068.     c) Accompany it with the information you received as to the offer
  1069.     to distribute corresponding source code.  (This alternative is
  1070.     allowed only for noncommercial distribution and only if you
  1071.     received the program in object code or executable form with such
  1072.     an offer, in accord with Subsection b above.)
  1073.  
  1074. The source code for a work means the preferred form of the work for
  1075. making modifications to it.  For an executable work, complete source
  1076. code means all the source code for all modules it contains, plus any
  1077. associated interface definition files, plus the scripts used to
  1078. control compilation and installation of the executable.  However, as a
  1079. special exception, the source code distributed need not include
  1080. anything that is normally distributed (in either source or binary
  1081. form) with the major components (compiler, kernel, and so on) of the
  1082. operating system on which the executable runs, unless that component
  1083. itself accompanies the executable.
  1084.  
  1085. If distribution of executable or object code is made by offering
  1086. access to copy from a designated place, then offering equivalent
  1087. access to copy the source code from the same place counts as
  1088. distribution of the source code, even though third parties are not
  1089. compelled to copy the source along with the object code.
  1090.  
  1091.   4. You may not copy, modify, sublicense, or distribute the Program
  1092. except as expressly provided under this License.  Any attempt
  1093. otherwise to copy, modify, sublicense or distribute the Program is
  1094. void, and will automatically terminate your rights under this License.
  1095. However, parties who have received copies, or rights, from you under
  1096. this License will not have their licenses terminated so long as such
  1097. parties remain in full compliance.
  1098.  
  1099.   5. You are not required to accept this License, since you have not
  1100. signed it.  However, nothing else grants you permission to modify or
  1101. distribute the Program or its derivative works.  These actions are
  1102. prohibited by law if you do not accept this License.  Therefore, by
  1103. modifying or distributing the Program (or any work based on the
  1104. Program), you indicate your acceptance of this License to do so, and
  1105. all its terms and conditions for copying, distributing or modifying
  1106. the Program or works based on it.
  1107.  
  1108.   6. Each time you redistribute the Program (or any work based on the
  1109. Program), the recipient automatically receives a license from the
  1110. original licensor to copy, distribute or modify the Program subject to
  1111. these terms and conditions.  You may not impose any further
  1112. restrictions on the recipients' exercise of the rights granted herein.
  1113. You are not responsible for enforcing compliance by third parties to
  1114. this License.
  1115.  
  1116.   7. If, as a consequence of a court judgment or allegation of patent
  1117. infringement or for any other reason (not limited to patent issues),
  1118. conditions are imposed on you (whether by court order, agreement or
  1119. otherwise) that contradict the conditions of this License, they do not
  1120. excuse you from the conditions of this License.  If you cannot
  1121. distribute so as to satisfy simultaneously your obligations under this
  1122. License and any other pertinent obligations, then as a consequence you
  1123. may not distribute the Program at all.  For example, if a patent
  1124. license would not permit royalty-free redistribution of the Program by
  1125. all those who receive copies directly or indirectly through you, then
  1126. the only way you could satisfy both it and this License would be to
  1127. refrain entirely from distribution of the Program.
  1128.  
  1129. If any portion of this section is held invalid or unenforceable under
  1130. any particular circumstance, the balance of the section is intended to
  1131. apply and the section as a whole is intended to apply in other
  1132. circumstances.
  1133.  
  1134. It is not the purpose of this section to induce you to infringe any
  1135. patents or other property right claims or to contest validity of any
  1136. such claims; this section has the sole purpose of protecting the
  1137. integrity of the free software distribution system, which is
  1138. implemented by public license practices.  Many people have made
  1139. generous contributions to the wide range of software distributed
  1140. through that system in reliance on consistent application of that
  1141. system; it is up to the author/donor to decide if he or she is willing
  1142. to distribute software through any other system and a licensee cannot
  1143. impose that choice.
  1144.  
  1145. This section is intended to make thoroughly clear what is believed to
  1146. be a consequence of the rest of this License.
  1147.  
  1148.   8. If the distribution and/or use of the Program is restricted in
  1149. certain countries either by patents or by copyrighted interfaces, the
  1150. original copyright holder who places the Program under this License
  1151. may add an explicit geographical distribution limitation excluding
  1152. those countries, so that distribution is permitted only in or among
  1153. countries not thus excluded.  In such case, this License incorporates
  1154. the limitation as if written in the body of this License.
  1155.  
  1156.   9. The Free Software Foundation may publish revised and/or new versions
  1157. of the General Public License from time to time.  Such new versions will
  1158. be similar in spirit to the present version, but may differ in detail to
  1159. address new problems or concerns.
  1160.  
  1161. Each version is given a distinguishing version number.  If the Program
  1162. specifies a version number of this License which applies to it and "any
  1163. later version", you have the option of following the terms and conditions
  1164. either of that version or of any later version published by the Free
  1165. Software Foundation.  If the Program does not specify a version number of
  1166. this License, you may choose any version ever published by the Free Software
  1167. Foundation.
  1168.  
  1169.   10. If you wish to incorporate parts of the Program into other free
  1170. programs whose distribution conditions are different, write to the author
  1171. to ask for permission.  For software which is copyrighted by the Free
  1172. Software Foundation, write to the Free Software Foundation; we sometimes
  1173. make exceptions for this.  Our decision will be guided by the two goals
  1174. of preserving the free status of all derivatives of our free software and
  1175. of promoting the sharing and reuse of software generally.
  1176. {END OF GPL CONDITIONS}
  1177.             GNU GENERAL PUBLIC LICENSE
  1178.                 NO WARRANTY
  1179.  
  1180.   11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
  1181. FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
  1182. OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
  1183. PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
  1184. OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  1185. MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
  1186. TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
  1187. PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
  1188. REPAIR OR CORRECTION.
  1189.  
  1190.   12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
  1191. WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
  1192. REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
  1193. INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
  1194. OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
  1195. TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
  1196. YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
  1197. PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
  1198. POSSIBILITY OF SUCH DAMAGES.
  1199.